package com.firefly.admin.common.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import com.firefly.admin.common.constant.Constants;
import com.firefly.admin.common.vo.LoginUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtTokenUtil {
    private static String SECRET;
    private static String ISS;
    private static String TOKEN_HEADER;
    private static String TOKEN_HEAD;
    private static final Integer EXPIRE_TIME = 1800;

    // 创建token
    public static String createToken(String userName, String userToken) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(Constants.JwtToken.LOGIN_USER_KEY, userToken);
        claims.put(Constants.JwtToken.USER_NAME, userName);
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setIssuer(ISS)
                .setSubject(userName)
                .setClaims(claims)
                .setIssuedAt(DateUtil.getNowDate())
                .setExpiration(getTokenExpiration())
                .compact();
    }

    public static String getRedisTokenKey(String userName) {
        return Constants.JwtToken.LOGIN_USER_KEY + userName;
    }

    public static Date getTokenExpiration() {
        Date nowDate = DateUtil.getNowDate();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate);
        calendar.add(Calendar.DATE, 7);
        return calendar.getTime();
    }

    public static LoginUser getLoginUser() {
        String userKey = getUserKey();
        return (LoginUser) RedisUtil.get(userKey);
    }

    public static Long getLoginUserId() {
        String userKey = getUserKey();
        LoginUser loginUser = (LoginUser) RedisUtil.get(userKey);
        return loginUser.getFySystemUser().getUserId();
    }

    public static Long getLoginUserId(String Token) {
        String userKey = getUserKey(Token);
        LoginUser loginUser = (LoginUser) RedisUtil.get(userKey);
        return loginUser.getFySystemUser().getUserId();
    }

    // 从token中获取用户名
    public static String getUserName(String token) {
        return (String) getTokenBody(token).get(Constants.JwtToken.USER_NAME);
    }

    // 是否已过期
    public static boolean isExpiration(String token) {
        boolean isExpiration = getTokenBody(token).getExpiration().before(DateUtil.getNowDate());
        String userKey = getUserKey();
        Object loginUser = RedisUtil.get(userKey);
        if (loginUser == null) {
            return true;
        }
        if (!isExpiration) {
            refreshToken();
        }
        return isExpiration;
    }

    /**
     * 刷新令牌有效期
     */
    public static void refreshToken() {
        // 根据uuid将loginUser缓存
        String userKey = getUserKey();
        RedisUtil.expire(userKey, EXPIRE_TIME);
    }

    public static String getUserKey() {
        String token = getToken();
        Claims tokenBody = getTokenBody(token);
        return (String) tokenBody.get(Constants.JwtToken.LOGIN_USER_KEY);
    }

    public static String getUserKey(String token) {
        Claims tokenBody = getTokenBody(token);
        return (String) tokenBody.get(Constants.JwtToken.LOGIN_USER_KEY);
    }

    private static Claims getTokenBody(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
    }

    public static String getToken() {
        String token = RequestUtil.getRequest().getHeader(TOKEN_HEADER);
        if (StringUtils.isNotEmpty(token) && token.startsWith(TOKEN_HEAD)) {
            token = token.replace(TOKEN_HEAD, "");
        }
        return token;
    }

    @Value(value = "${jwt.secret}")
    public void setSECRET(String SECRET) {
        JwtTokenUtil.SECRET = SECRET;
    }

    @Value(value = "${jwt.iss}")
    public void setISS(String ISS) {
        JwtTokenUtil.ISS = ISS;
    }

    @Value("${jwt.tokenHeader}")
    public void setTOKEN_HEADER(String TOKEN_HEADER) {
        JwtTokenUtil.TOKEN_HEADER = TOKEN_HEADER;
    }

    @Value("${jwt.tokenHead}")
    public void setTOKEN_HEAD(String TOKEN_HEAD) {
        JwtTokenUtil.TOKEN_HEAD = TOKEN_HEAD;
    }
}
